package utsc.apps.utschedule.ui.activities;

import java.util.ArrayList;
import java.util.Collections;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.ActionBar.TabListener;
import com.actionbarsherlock.view.MenuItem;

import utsc.apps.utschedule.R;
import utsc.apps.utschedule.UTSCheduleApp;
import utsc.apps.utschedule.UTSCheduleHomeActivity;
import utsc.apps.utschedule.classes.Assignment;
import utsc.apps.utschedule.classes.Course;
import utsc.apps.utschedule.classes.CourseMark;
import utsc.apps.utschedule.classes.Exam;
import utsc.apps.utschedule.classes.ForecastResult;
import utsc.apps.utschedule.classes.GenericTask;
import utsc.apps.utschedule.classes.Timetable;
import utsc.apps.utschedule.classes.UofTGrade;
import utsc.apps.utschedule.ui.InputDialogFragment;
import utsc.apps.utschedule.ui.InputDialogFragment.OnInputListener;
import utsc.apps.utschedule.ui.MessageDialogFragment;
import utsc.apps.utschedule.ui.activities.CalculatorListFragment.OnForecastListener;
import utsc.apps.utschedule.ui.activities.CalculatorPredictListFragment.OnCourseMarkSelectedListener;
import utsc.apps.utschedule.ui.activities.adapters.CalculatorListAdapter;
import utsc.apps.utschedule.ui.activities.adapters.CourseSpinnerAdapter;
import utsc.apps.utschedule.ui.activities.adapters.ForecastResultAdapter;
import utsc.apps.utschedule.ui.activities.adapters.TaskAdapter;
import utsc.apps.utschedule.util.AppUtils;
import utsc.apps.utschedule.util.Validator;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.NavUtils;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.SparseBooleanArray;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RadioGroup;
import android.widget.TextView;

/**
 * The main activity to host a view pager to show {@link utsc.apps.utschedule.ui.activities.CalculatorListFragment CalculatorListFragment} and {@link utsc.apps.utschedule.ui.ExamListFragment ExamListFragment} 
 * in a tabular manner. 
 * @author 
 *
 */
public class CalculatorMainActivity extends GenericFragmentActivity implements OnClickListener,OnInputListener,OnCourseMarkSelectedListener,OnForecastListener{

	private boolean _updated=true;
	private ViewPager _pager;
	private AssignmentExamPagerAdapter _PagerAdapter;
	private ArrayList<Fragment> _fragments;
	public static final int TAG_ASSIGNMENT=1;
	public static final int TAG_EXAM=2;
	private CourseMark _selectedCourseMark;
	private Course _selectedCourse;
	private ArrayList<Course> _courses;
	private ArrayList<GenericTask> _tasks;
	private static final String PREFERENCE_NAME="CalculatorPreferences";
	public static final String TAG="utsc.apps.utschedule.ui.activities.CalculatorMainActivity";
	private final Validator _validator=Validator.newInstance(TAG);
	private static final String DESIRED_GPA_KEY="DesiredGPA";
	private ArrayList<ForecastResult> _forecastResults;
	private String _forecastDesiredMarkLabel;
	/**
	 * the empty layout for no active timetable set 
	 */
	private LinearLayout _emptyLayout;
	/**
	 * the activity class name that started this activity if set 
	 */
	private String _fromActivity;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		Intent startIntent=getIntent();
		if (startIntent!=null) {
			//set the fromActivity string 
			_fromActivity=startIntent.getStringExtra("fromActivity");
		}
		
		setContentView(R.layout.activity_calculator);
		_emptyLayout=(LinearLayout) findViewById(R.id.empty_timetable_layout);
		setupAssignmentList();
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		if (!_updated) {
			_PagerAdapter.notifyDataSetChanged();
			_updated=true;
		}
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case android.R.id.home:
			if (_fromActivity==null) {
				navigateUp();
			}else {
				finish();
			}
			
			break;

		default:
			break;
		}
		return true;
	}
	
	@Override
	public void onBackPressed() {
		if (_fromActivity==null) {
			navigateUp();
		}
		else {
			super.onBackPressed();
		}
	}
	
	private void navigateUp() {
			Intent intent=new Intent(this,UTSCheduleHomeActivity.class);
			if (NavUtils.shouldUpRecreateTask(this, intent)) {
				NavUtils.navigateUpTo(this, intent);
			}else {
				NavUtils.navigateUpFromSameTask(this);
			}
	}
	
	/**
	 * A general setup method to setup the view pager.
	 */
	public void setupAssignmentList() {
		UTSCheduleApp app=(UTSCheduleApp) getApplication();
		Timetable t=app.get_currentActiveTimetable();
		//we only setup the view pager if we have an active timetable
		if (t!=null) {
			//hide the empty view
			_emptyLayout.setVisibility(View.GONE);
			_fragments=new ArrayList<Fragment>();
			
			//setup the two fragments
			CalculatorListFragment fragment1=CalculatorListFragment.newInstance(t.get_timetableID());
			CalculatorPredictListFragment fragment2=new CalculatorPredictListFragment();
			
			_fragments.add(fragment1);
			_fragments.add(fragment2);
			_pager=(ViewPager)findViewById(R.id.pager);
			_PagerAdapter=new AssignmentExamPagerAdapter(getSupportFragmentManager(), _fragments, this);
			_pager.setAdapter(_PagerAdapter);
			_pager.setOffscreenPageLimit(2);
			_pager.setOnPageChangeListener(_PagerAdapter);
			
			//also setup the tabs for navigation
			
			final ActionBar actionBar=getSupportActionBar();
			actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
			actionBar.setDisplayHomeAsUpEnabled(true);
			Tab forecastTab=actionBar.newTab().setText("GPA Forecasting").setTabListener(_PagerAdapter);
			Tab predictTab=actionBar.newTab().setText("GPA Prediction").setTabListener(_PagerAdapter);
			actionBar.addTab(forecastTab);
			actionBar.addTab(predictTab);
			
			
		}else {
			_emptyLayout.setVisibility(View.VISIBLE);
		}
		
	}
	
	@Override
	public void onClick(View v) {
		
	}
	
	public void selectTab(int position){
		getSupportActionBar().setSelectedNavigationItem(position);
	}
	
	public void selectPage(int position){
		_pager.setCurrentItem(position);
	}
	
	public static class AssignmentExamPagerAdapter extends FragmentStatePagerAdapter implements OnPageChangeListener, TabListener{
		public static final int COUNT=2;
		private ArrayList<Fragment> _fragmentList;
		private Context _context;
				
		public AssignmentExamPagerAdapter(FragmentManager fm, ArrayList<Fragment> fragmentList,Context context) {
			super(fm);
			this._fragmentList=fragmentList;
			this._context=context;
		}
		@Override
		public Fragment getItem(int arg0) {
			return _fragmentList.get(arg0);
		}
		
		public void notifyDataSetChanged(int courseID) {
			super.notifyDataSetChanged();
			if (_fragmentList!=null) {
				((CalculatorListAdapter)((CalculatorListFragment)_fragmentList.get(0)).getExpandableListAdapter()).notifyDataSetChanged(courseID);
			}
		}
		
		@Override
		public int getCount() {
			return COUNT;
		}
		
		@Override
		public int getItemPosition(Object object) {
			return POSITION_NONE;
		}
		
		@Override
		public void onTabSelected(Tab tab, FragmentTransaction ft) {
			((CalculatorMainActivity)_context).selectPage(tab.getPosition());
		}
		@Override
		public void onTabUnselected(Tab tab, FragmentTransaction ft) {
			
		}
		@Override
		public void onTabReselected(Tab tab, FragmentTransaction ft) {
			
		}
		@Override
		public void onPageScrollStateChanged(int arg0) {
		}
		@Override
		public void onPageScrolled(int arg0, float arg1, int arg2) {
		}
		@Override
		public void onPageSelected(int arg0) {
			((CalculatorMainActivity)_context).selectTab(arg0);
		}
	}
	
	@Override
	public void setupInputs(View v) {
		switch (v.getId()) {
		case R.id.course_mark_layout:
			if (_selectedCourseMark!=null) {
				TextView course=(TextView) v.findViewById(R.id.frm_txt_course);
				TextView mark=(TextView) v.findViewById(R.id.frm_txt_mark);
				RadioGroup weight=(RadioGroup) v.findViewById(R.id.frm_radiogrp_courseweight);
				course.setText(_selectedCourseMark.get_name());
				mark.setText(String.valueOf(_selectedCourseMark.get_mark()));
				if (_selectedCourseMark.get_weight()==1.0) {
					weight.check(R.id.frm_radio_whole);
				}
			}
			break;
		case R.id.course_forecast_layout:
			if (_courses!=null && !_courses.isEmpty()) {
				SharedPreferences sharedPreferences=getSharedPreferences(PREFERENCE_NAME, MODE_PRIVATE);
				String desiredGpaString=sharedPreferences.getString(DESIRED_GPA_KEY, "3.0");
				((TextView)v.findViewById(R.id.frm_txt_desire_gpa)).setText(desiredGpaString);
				ListView listView=(ListView)v.findViewById(R.id.lst_forecast);
				listView.setCacheColorHint(Color.TRANSPARENT);
				listView.setAdapter(new CourseSpinnerAdapter(this, android.R.layout.select_dialog_multichoice, _courses));
			}
			break;
		case R.id.forecast_result_layout:
			if (_forecastResults!=null&&!_forecastResults.isEmpty()) {
				TextView lbResult=(TextView)v.findViewById(R.id.lb_result);
				lbResult.setText(String.format(AppUtils.LABEL_FORECAST_RESULT,_forecastDesiredMarkLabel));
				ListView foreacastListView=(ListView)v.findViewById(R.id.lst_forecast_result);
				ForecastResultAdapter adapter=new ForecastResultAdapter(this, 0, _forecastResults);
				foreacastListView.setAdapter(adapter);
			}
			break;
		case R.id.task_forecast_layout:
			if (_tasks!=null && !_tasks.isEmpty()) {
				((TextView)v.findViewById(R.id.frm_txt_desire_grade)).setText(String.valueOf(_selectedCourse.get_grade().get_percentage()));
				ListView taskForeacastListView=(ListView)v.findViewById(R.id.lst_forecast);
				taskForeacastListView.setCacheColorHint(Color.TRANSPARENT);
				TaskAdapter taskAdapter=new TaskAdapter(this, android.R.layout.select_dialog_multichoice, _tasks);
				taskForeacastListView.setAdapter(taskAdapter);
			}
			break;
		default:
			break;
		}
	}

	@Override
	public void onInputSaveListener(View v) {
		switch (v.getId()) {
			case R.id.course_mark_layout:
				TextView course=(TextView) v.findViewById(R.id.frm_txt_course);
				TextView mark=(TextView) v.findViewById(R.id.frm_txt_mark);
				RadioGroup weight=(RadioGroup) v.findViewById(R.id.frm_radiogrp_courseweight);
				_selectedCourseMark.set_name(course.getText().toString());
				_selectedCourseMark.set_mark(Double.parseDouble(mark.getText().toString()));
				if (weight.getCheckedRadioButtonId()==R.id.frm_radio_half) {
					_selectedCourseMark.set_weight(0.5);
				}else {
					_selectedCourseMark.set_weight(1.0);
				}
				((CalculatorPredictListFragment)_fragments.get(1)).updateCourseMark(_selectedCourseMark, _selectedCourseMark.get_position());
				break;
			case R.id.course_forecast_layout:
				ListView listView=(ListView)v.findViewById(R.id.lst_forecast);
				SparseBooleanArray checkItems=listView.getCheckedItemPositions();
				TextView desiredGpa=(TextView)v.findViewById(R.id.frm_txt_desire_gpa);
				String desiredGpaString=desiredGpa.getText().toString();
				_validator.reset();
				_validator.checkNull(desiredGpaString, String.format(AppUtils.ERROR_MESSAGE_GENERIC_EMPTY_PARAMERTERIZED,"Desired GPA"));
				if (_validator.get_errorMessages()!=null) {
					showDialogFragment(InputDialogFragment.newInstance("GPA Forecast", R.layout.dialog_forecast,"Forecast"), InputDialogFragment.TAG);
					showDialogFragment(MessageDialogFragment.newInstance(String.format(AppUtils.ERROR_TITLE_GENERIC_PARAMERTERIZED, "GPA Forecast"), _validator.get_errorMessages()), MessageDialogFragment.TAG);
				}else {
					forecastCourseGPA(checkItems,Double.parseDouble(desiredGpa.getText().toString()));
					SharedPreferences sharedPreferences=getSharedPreferences(PREFERENCE_NAME, MODE_PRIVATE);
					sharedPreferences.edit().putString(DESIRED_GPA_KEY, desiredGpaString).commit();
				}
				break;
			case R.id.task_forecast_layout:
				ListView taskListView=(ListView)v.findViewById(R.id.lst_forecast);
				SparseBooleanArray checkTaskItems=taskListView.getCheckedItemPositions();
				TextView desiredGrade=(TextView)v.findViewById(R.id.frm_txt_desire_grade);
				String desiredGradeString=desiredGrade.getText().toString();
				_validator.reset();
				_validator.checkNull(desiredGradeString, String.format(AppUtils.ERROR_MESSAGE_GENERIC_EMPTY_PARAMERTERIZED,"Desired Grade"));
				if (_validator.get_errorMessages()!=null) {
					showDialogFragment(InputDialogFragment.newInstance("Course Grade Forecast", R.layout.dialog_forecast_course_grade,"Forecast"), InputDialogFragment.TAG);
					showDialogFragment(MessageDialogFragment.newInstance(String.format(AppUtils.ERROR_TITLE_GENERIC_PARAMERTERIZED, "Course Grade Forecast"), _validator.get_errorMessages()), MessageDialogFragment.TAG);
				}else {
					forecastCourseGrade(checkTaskItems,Double.parseDouble(desiredGrade.getText().toString()));
					//SharedPreferences sharedPreferences=getSharedPreferences(PREFERENCE_NAME, MODE_PRIVATE);
					//sharedPreferences.edit().putString(DESIRED_GPA_KEY, desiredGpaString).commit();
				}
				break;
			
			default:
				break;
		}
	}
	
	private void forecastCourseGrade(SparseBooleanArray selectedItems, double desiredGrade) {
		_forecastDesiredMarkLabel=String.valueOf(desiredGrade)+"% final grade";
		if (selectedItems.size()>0) {
			int taskSize=_tasks.size();
			double totalPercentLeft=0;
			double totalPercentCompleted=_selectedCourse.get_grade().get_total();
			ArrayList<GenericTask> selectedTasks=new ArrayList<GenericTask>();
			//double desiredGpa=3.5;
			double sumGrade=_selectedCourse.get_grade().get_percentage()/100*totalPercentCompleted;
			for (int i = 0; i < taskSize; i++) {
				if (selectedItems.get(i, false)) {
					GenericTask task=_tasks.get(i);
					totalPercentLeft+=task.get_weight();
					selectedTasks.add(task);
				}
			}
						
			if (!selectedTasks.isEmpty()) {
				_forecastResults=new ArrayList<ForecastResult>(selectedTasks.size());
				double desirePercentage=totalPercentCompleted+totalPercentLeft;
				double gradeDifference=desiredGrade/100*desirePercentage-sumGrade;
				for (GenericTask task:selectedTasks) {
					
					double currentPercent=task.get_weight();
					double percentDiff=currentPercent/totalPercentLeft;
					double mark=Math.floor(percentDiff*gradeDifference+0.5);
					if (task instanceof Assignment || task instanceof Exam) {
						_forecastResults.add(new ForecastResult(task.toString()+" "+task.get_weight()+"%", "0%", String.valueOf(mark)+"%"));
					}else {
						_forecastResults.add(new ForecastResult("Remaining "+currentPercent+"%", "0%", String.valueOf(mark)+"%"));
					}
					
				}
				showDialogFragment(InputDialogFragment.newInstance("Forecast results", R.layout.dialog_forecast_result), InputDialogFragment.TAG);
			}
		}
		
	}
	
	private void forecastCourseGPA(SparseBooleanArray selectedItems, double desiredGpa) {
		_forecastDesiredMarkLabel=String.valueOf(desiredGpa)+" final GPA";
		if (selectedItems.size()>0) {
			int courseSize=_courses.size();
			ArrayList<Course> selectedCourses=new ArrayList<Course>();
			double totalPercentLeft=0;
			//double desiredGpa=3.5;
			double sumGpa=0;
			for (int i = 0; i < courseSize; i++) {
				Course course=_courses.get(i);
				if (selectedItems.get(i, false)) {
					
					double percentLeft=100-course.get_grade().get_total();
					/*if (course.get_grade().get_GPA()>=desiredGpa) {
						countForecast++;
					}*/
					selectedCourses.add(course);
					totalPercentLeft+=percentLeft;
					sumGpa+=course.get_weight()*(course.get_grade().get_total()/100)*course.get_grade().get_GPA();
				}else {
					sumGpa+=course.get_grade().get_GPA();
				}
			}
			Collections.reverse(selectedCourses);
			
			if (!selectedCourses.isEmpty()) {
				_forecastResults=new ArrayList<ForecastResult>(selectedCourses.size());
				double desireSumGpa=desiredGpa*courseSize;
				double gpaDifference=desireSumGpa-sumGpa;
				for (Course course : selectedCourses) {
					UofTGrade grade=course.get_grade();
					
					double courseGpa=grade.get_GPA();
					double currentGpa=course.get_weight()*(grade.get_total()/100)*courseGpa;
					double currentPercent=grade.get_percentage();
					double mark=0;
					double percentDiff=(100-grade.get_total())/totalPercentLeft;
					double goalGpa=currentGpa+percentDiff*gpaDifference;
					if (goalGpa>4 && currentGpa<4) {
						goalGpa=4;
						mark=85;
					}else if (currentGpa==4) {
						goalGpa=4;
						mark=currentPercent;
					}
					else {
						mark=UofTGrade.getMinGrade(goalGpa);
					}
					_forecastResults.add(new ForecastResult(course.get_courseCode(), String.valueOf(currentPercent), String.valueOf(mark)));
				}
				showDialogFragment(InputDialogFragment.newInstance("Forecast results", R.layout.dialog_forecast_result), InputDialogFragment.TAG);
			}
		}
		
	}

	@Override
	public void onCourseMarkItemClicked(CourseMark mark, int position) {
		_selectedCourseMark=mark;
		if (_selectedCourseMark==null) {
			_selectedCourseMark=new CourseMark();
			_selectedCourseMark.set_position(position);
			showDialogFragment(InputDialogFragment.newInstance("Add course mark", R.layout.dialog_course_marks, "Add"), InputDialogFragment.TAG);
		}else {
			showDialogFragment(InputDialogFragment.newInstance("Update course mark", R.layout.dialog_course_marks, "Update"), InputDialogFragment.TAG);
		}
		
	}

	@Override
	public void onGPAForecast(ArrayList<Course> courses) {
		_courses=courses;
		showDialogFragment(InputDialogFragment.newInstance("GPA Forecast", R.layout.dialog_forecast,"Forecast"), InputDialogFragment.TAG);
	}

	@Override
	public void onCourseForecast(Course selectedCourse) {
		_selectedCourse=selectedCourse;
		ArrayList<GenericTask> tasks=selectedCourse.get_taskList();
		ArrayList<GenericTask> unfinishedTasks=new ArrayList<GenericTask>();
		double finishedWeight=0;
		for (GenericTask genericTask : tasks) {
			if ((genericTask.get_mark()==0||genericTask.get_total()==0) && genericTask.get_weight()!=0) {
				if (genericTask.get_total()==0) {
					GenericTask copyTask=genericTask.copyTask();
					copyTask.set_total(genericTask.get_weight());
					unfinishedTasks.add(copyTask);
					
				}else {
					unfinishedTasks.add(genericTask);
				}
			}
			finishedWeight+=genericTask.get_weight();
		}
		
		if (finishedWeight<100) {
			GenericTask unfinishedTask=new GenericTask();
			unfinishedTask.set_total(100-finishedWeight);
			unfinishedTask.set_weight(100-finishedWeight);
			unfinishedTasks.add(unfinishedTask);
		}
		_tasks=unfinishedTasks;
		showDialogFragment(InputDialogFragment.newInstance("Course Grade Forecast", R.layout.dialog_forecast_course_grade,"Forecast"), InputDialogFragment.TAG);
	}

	@Override
	public void onForecastAction() {
		// TODO Auto-generated method stub
		
	}

}
